package com.duoduo.common.util.helper;

import com.duoduo.common.api.exception.CreateKeyException;
import com.duoduo.common.api.help.JoinPointInnerUtil;
import com.duoduo.common.api.help.Md5InnerUtil;
import com.duoduo.common.api.tuple.TwoTuple;
import com.duoduo.common.util.myhelper.SpringElUtil;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import com.duoduo.common.util.anno.method.KeyRule;
import com.duoduo.common.util.anno.param.KeyParam;
import com.duoduo.common.util.myhelper.StringUtil;

import java.lang.annotation.Annotation;
import java.util.List;

/**key帮助类
 * @author duoduo
 *
 */
public class KeyHelper {
	
	/**分析输入参数，生成key
	 * @param keyRule: key的生成规则
	 * @param joinpoint
	 * @param methodName: 被拦截的方法名称
	 * @param objs: 输入参数值
	 * @return key
	 * @throws CreateKeyException 生成key失败
	 */
	public static String createKey(KeyRule keyRule, ProceedingJoinPoint joinpoint, String methodName, Object[] objs) throws CreateKeyException {
		try{
			String key = null;
			//计算缓存key
			if(StringUtils.isNotEmpty(keyRule.key())){
				String[] paramNames = JoinPointInnerUtil.getParamterNames(joinpoint);
				Object tmp = SpringElUtil.getCacheKey(objs, paramNames, keyRule.key());
				if(tmp != null){
					key = tmp.toString();
				}
			} else {
				List<TwoTuple<Annotation, Object>> objsKeys = JoinPointInnerUtil.getMethodArgValuesByAnnotations(joinpoint, KeyParam.class);
				key = createKeyStr(keyRule, objsKeys, methodName, objs);
			}
			return key;
		} catch (Exception e){
        	throw new CreateKeyException("(createKey) get key from myself rule error: ", e);
        }
	}
	
	/**分析输入参数，生成key列表
	 * @param keyRule: key的生成规则
	 * @param joinpoint
	 * @param methodName: 被拦截的方法名称
	 * @param objs: 输入参数值
	 * @return key
	 * @throws CreateKeyException 生成key失败
	 */
	@SuppressWarnings("unchecked")
	public static List<String> createKeyList(KeyRule keyRule, ProceedingJoinPoint joinpoint, String methodName, Object[] objs) throws CreateKeyException {
		try{
			//计算缓存key
			if(StringUtils.isNotEmpty(keyRule.key())){
				String[] paramNames = JoinPointInnerUtil.getParamterNames(joinpoint);
				Object tmp = SpringElUtil.getCacheKey(objs, paramNames, keyRule.key());
				if(tmp != null && tmp instanceof List){
					return (List<String>)tmp;
				}else {
					throw new CreateKeyException("(createKey) create list is null");
				}
			}else {
				throw new CreateKeyException("(createKey) keyRule key is null");
			}
		} catch (Exception e){
        	throw new CreateKeyException("(createKey) get key from myself rule error: ", e);
        }
	}

	/**生成缓存的keyStr
	 * @param keyRule: key的生成规则
	 * @param objsKeys: 有KeyParam注解的参数信息
	 * @param methodName: 被拦截的方法名称
	 * @param objs: 输入参数值
	 * @return
	 * @throws CreateKeyException 生成key失败
	 */
	private static String createKeyStr(KeyRule keyRule, List<TwoTuple<Annotation, Object>> objsKeys, String methodName, Object[] objs) throws CreateKeyException {
		try{
			String keyStr = null;
			StringBuilder sb = new StringBuilder();
			if(keyRule.useMethodKey()){
				sb.append(methodName);
			}
			if(objsKeys.isEmpty()){
				sb.append(StringUtil.arrayToString(objs));
			}else{
				Object[] objsInner = objsKeys.stream().map(x -> x.secord).toArray();
				sb.append(StringUtil.arrayToString(objsInner));
			}
			if(keyRule.useSecretKey()){
				keyStr = Md5InnerUtil.md5(sb.toString(), 16, true);
			}else{
				keyStr = sb.toString();
			}
			return keyStr;
		} catch (Exception e){
        	throw new CreateKeyException("(createKey) get key from myself rule error: ", e);
        }
	}

}
